using Microsoft.Phone.Controls.Maps.ConfigService;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net.NetworkInformation;
using System.Runtime.CompilerServices;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
using System.Windows.Threading;
using System.Xml;
namespace Microsoft.Phone.Controls.Maps.Core
{
	internal class MapConfigurationFromService : MapConfigurationProvider
	{
		private readonly object configLock = new object();
		private readonly Dictionary<string, Collection<MapConfigurationGetSectionRequest>> requestQueue;
		private readonly Collection<string> requestedSections;
		private readonly MapControlConfigurationServiceClient serviceClient;
		private MapControlConfigurationRequest configRequest;
		private string configRequestKey;
		private bool detectingNetworkChanged;
		private int retryLimit = 10;
		private bool isConfigLoaded;
		private DispatcherTimer networkChangePollTimer;
		public override event EventHandler<MapConfigurationLoadedEventArgs> Loaded
		{
			[MethodImpl(32)]
			add
			{
				this.Loaded = (EventHandler<MapConfigurationLoadedEventArgs>)Delegate.Combine(this.Loaded, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Loaded = (EventHandler<MapConfigurationLoadedEventArgs>)Delegate.Remove(this.Loaded, value);
			}
		}
		public MapConfigurationFromService(Uri address)
		{
			HttpTransportBindingElement httpTransportBindingElement = new HttpTransportBindingElement();
			CustomBinding binding = new CustomBinding(new BindingElement[]
			{
				new BinaryMessageEncodingBindingElement(),
				httpTransportBindingElement
			});
			this.serviceClient = new MapControlConfigurationServiceClient(binding, new EndpointAddress(address, new AddressHeader[0]));
			this.serviceClient.GetConfigurationCompleted += new EventHandler<GetConfigurationCompletedEventArgs>(this.ServiceClient_GetConfigurationCompleted);
			base.Sections = new Dictionary<string, MapConfigurationSection>();
			this.requestQueue = new Dictionary<string, Collection<MapConfigurationGetSectionRequest>>();
			this.requestedSections = new Collection<string>();
		}
		public override void LoadConfiguration()
		{
		}
		public override void GetConfigurationSection(string version, string sectionName, string culture, MapConfigurationCallback callback, object userState)
		{
			bool flag;
			if (!(flag = base.ContainConfigurationSection(version, sectionName, culture)))
			{
				string configurationKey = MapConfigurationProvider.GetConfigurationKey(version, sectionName, culture);
				object obj;
				Monitor.Enter(obj = this.configLock);
				bool flag2;
				try
				{
					flag2 = (!(flag = (base.ContainConfigurationSection(version, sectionName, culture) || this.requestedSections.Contains(configurationKey))) && !this.requestQueue.ContainsKey(configurationKey));
					if (!this.requestQueue.ContainsKey(configurationKey))
					{
						this.requestQueue.Add(configurationKey, new Collection<MapConfigurationGetSectionRequest>());
					}
					if (!flag)
					{
						this.requestQueue.get_Item(configurationKey).Add(new MapConfigurationGetSectionRequest(version, sectionName, culture, callback, userState));
					}
				}
				finally
				{
					Monitor.Exit(obj);
				}
				if (flag2)
				{
					MapControlConfigurationRequest mapControlConfigurationRequest = new MapControlConfigurationRequest();
					mapControlConfigurationRequest.ExecutionOptions = new ExecutionOptions();
					mapControlConfigurationRequest.ExecutionOptions.SuppressFaults = true;
					if (string.IsNullOrEmpty(culture))
					{
						mapControlConfigurationRequest.Culture = culture;
					}
					mapControlConfigurationRequest.Version = version;
					mapControlConfigurationRequest.SectionName = sectionName;
					this.configRequest = mapControlConfigurationRequest;
					this.configRequestKey = configurationKey;
					string filename = this.GetFilename(configurationKey);
					try
					{
						using (IsolatedStorageFile userStoreForApplication = IsolatedStorageFile.GetUserStoreForApplication())
						{
							if (userStoreForApplication.FileExists(filename))
							{
								using (IsolatedStorageFileStream isolatedStorageFileStream = new IsolatedStorageFileStream(filename, 3, userStoreForApplication))
								{
									try
									{
										this.LoadConfig(configurationKey, XmlReader.Create(isolatedStorageFileStream));
									}
									catch (XmlException)
									{
									}
								}
							}
						}
					}
					catch (IsolatedStorageException)
					{
					}
					this.MakeServiceRequest();
				}
			}
			if (flag && callback != null)
			{
				callback(base.GetSection(version, sectionName, culture), userState);
			}
		}
		private void MakeServiceRequest()
		{
			if (NetworkInterface.GetIsNetworkAvailable())
			{
				this.retryLimit--;
				if (this.configRequest != null && this.configRequestKey != null)
				{
					this.serviceClient.GetConfigurationAsync(this.configRequest, this.configRequestKey);
					return;
				}
			}
			else
			{
				if (!this.isConfigLoaded && !this.detectingNetworkChanged)
				{
					this.detectingNetworkChanged = true;
					if (this.networkChangePollTimer == null)
					{
						DispatcherTimer dispatcherTimer = new DispatcherTimer();
						dispatcherTimer.set_Interval(TimeSpan.FromSeconds(5.0));
						this.networkChangePollTimer = dispatcherTimer;
						this.networkChangePollTimer.add_Tick(new EventHandler(this.NetworkChangePollTimer_Tick));
					}
					this.networkChangePollTimer.Start();
				}
			}
		}
		private void NetworkChangePollTimer_Tick(object sender, EventArgs e)
		{
			if (NetworkInterface.GetIsNetworkAvailable())
			{
				this.detectingNetworkChanged = false;
				this.networkChangePollTimer.Stop();
				this.networkChangePollTimer.remove_Tick(new EventHandler(this.NetworkChangePollTimer_Tick));
				this.networkChangePollTimer = null;
				this.MakeServiceRequest();
			}
		}
		private void ServiceClient_GetConfigurationCompleted(object sender, GetConfigurationCompletedEventArgs e)
		{
			string requestKey = e.get_UserState() as string;
			if (e.get_Error() != null)
			{
				if (this.Loaded != null)
				{
					this.Loaded.Invoke(this, new MapConfigurationLoadedEventArgs(e.get_Error()));
				}
				if (this.retryLimit > 0)
				{
					this.MakeServiceRequest();
					return;
				}
				this.CallRequests(requestKey);
				return;
			}
			else
			{
				if (e.Result != null && e.Result.Configuration != null)
				{
					if (!this.isConfigLoaded)
					{
						this.LoadConfig(requestKey, XmlReader.Create(new StringReader(e.Result.Configuration)));
					}
					try
					{
						using (IsolatedStorageFile userStoreForApplication = IsolatedStorageFile.GetUserStoreForApplication())
						{
							using (IsolatedStorageFileStream isolatedStorageFileStream = new IsolatedStorageFileStream(this.GetFilename(requestKey), 2, userStoreForApplication))
							{
								string configuration = e.Result.Configuration;
								try
								{
									isolatedStorageFileStream.Write(new UTF8Encoding().GetBytes(configuration), 0, configuration.get_Length());
								}
								catch (IOException)
								{
								}
							}
						}
					}
					catch (IsolatedStorageException)
					{
					}
					return;
				}
				if (this.Loaded != null)
				{
					this.Loaded.Invoke(this, new MapConfigurationLoadedEventArgs(new ConfigurationNotLoadedException(ExceptionStrings.MapConfiguration_WebService_InvalidResult)));
				}
				this.CallRequests(requestKey);
				return;
			}
		}
		private void LoadConfig(string requestKey, XmlReader config)
		{
			this.isConfigLoaded = true;
			Dictionary<string, MapConfigurationSection> dictionary = MapConfigurationProvider.ParseConfiguration(config);
			object obj;
			Monitor.Enter(obj = this.configLock);
			try
			{
				using (Dictionary<string, MapConfigurationSection>.KeyCollection.Enumerator enumerator = dictionary.get_Keys().GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						string current = enumerator.get_Current();
						if (!base.Sections.ContainsKey(current))
						{
							base.Sections.set_Item(current, dictionary.get_Item(current));
						}
					}
				}
				this.requestedSections.Add(requestKey);
			}
			finally
			{
				Monitor.Exit(obj);
			}
			if (this.Loaded != null)
			{
				this.Loaded.Invoke(this, new MapConfigurationLoadedEventArgs(null));
			}
			this.CallRequests(requestKey);
		}
		private void CallRequests(string requestKey)
		{
			if (this.requestQueue.ContainsKey(requestKey))
			{
				Collection<MapConfigurationGetSectionRequest> collection = this.requestQueue.get_Item(requestKey);
				this.requestQueue.Remove(requestKey);
				using (IEnumerator<MapConfigurationGetSectionRequest> enumerator = collection.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						MapConfigurationGetSectionRequest current = enumerator.get_Current();
						if (current.Callback != null)
						{
							current.Callback(base.GetSection(current.Version, current.SectionName, current.Culture), current.UserState);
						}
					}
				}
			}
		}
		private string GetFilename(string requestKey)
		{
			return "MapControlConfiguration_" + requestKey + ".xml";
		}
	}
}
